/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { PackageTool } = require("../../src/ros_msg_utils/PackageTool");
const { XTools } = require("../XTools");

const worker = new Worker('ws_in_worker.js');

/**
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Access-Control-Allow-Origin: https://example.com
 */

const syncBuffer = new SharedArrayBuffer(1024);//同步一下读到哪里了，以免写消息时覆盖
const syncUint32Array = new Uint32Array(syncBuffer);

const sharedBuffer = new SharedArrayBuffer(1024 * 1024 * 30);
const sharedUint8Array = new Uint8Array(sharedBuffer);
var arrayOffset = 0;

class WsClient2 {
    static IS_CONNECTED = false;
    static callbackFuncs = {};
    static startConnect(addr) {//1.2.3.4:5678
        sharedUint8Array[0] = 0;
        arrayOffset = 0;
        syncUint32Array[0] = 0;
        worker.postMessage({ action: 'setBuffer', buffer: sharedBuffer, buffer2: syncBuffer });
        worker.postMessage({ action: 'startConnect', addr: addr });
    }
    static isConnected() {
        return WsClient2.IS_CONNECTED;
    }
    static registProcess(protocol, func) {
        if (WsClient2.IS_CONNECTED) {
            WsClient2.callbackFuncs[protocol] = func;
        }
    }
    static send(pt, compress = true) {
        if (WsClient2.IS_CONNECTED) {
            // if (pt.offset[0] > 1024) {
            //     console.log("send : ", pt.offset[0])
            // }
            if (XTools.ENABLE_COMPRESS && compress) {
                worker.postMessage({ action: 'send', data: pako.deflate(pt.buffer.subarray(0, pt.offset[0])) });
            } else {
                worker.postMessage({ action: 'send', data: pt.buffer.subarray(0, pt.offset[0]) });
            }
        }
    }

    // static processDataQueue() {
    //     while (data_queue.length > 0) {
    //         let data = data_queue.shift();
    //         let pt = new PackageTool(data);
    //         // pt.offset = [4];
    //         let protocol = pt.get_string();
    //         if (protocol in WsClient2.callbackFuncs) {
    //             WsClient2.callbackFuncs[protocol](pt);
    //         }
    //     }
    // }
    static processDataQueue() {
        while (sharedUint8Array[arrayOffset] != 0) {
            if (sharedUint8Array[arrayOffset] == 2) {
                arrayOffset = 0;
                continue;
            }
            let msg_len = new DataView(sharedUint8Array.buffer, arrayOffset + 1, 4).getInt32(0, true);
            let pt;
            if (XTools.ENABLE_COMPRESS) {
                pt = new PackageTool(pako.inflate(sharedUint8Array.subarray(arrayOffset + 5, arrayOffset + 5 + msg_len)));
            } else {
                pt = new PackageTool(sharedUint8Array.subarray(arrayOffset + 5, arrayOffset + 5 + msg_len));
            }
            // pt.offset = [4];
            let protocol = pt.get_string();
            if (protocol in WsClient2.callbackFuncs) {
                WsClient2.callbackFuncs[protocol](pt);
            }
            arrayOffset += 5 + msg_len;
            syncUint32Array[0] = arrayOffset;
        }
    }
}

var data_queue = [];
worker.onmessage = function (event) {
    const data = event.data;
    switch (data.action) {
        case 'onOpen':
            WsClient2.IS_CONNECTED = true;
            const { RosProto } = require("../../src/ros_msg_utils/RosProto");
            RosProto.registProcess();
            break;
        case 'onPackage':
            // console.log("onPackage2", data.data.length)
            data_queue.push(data.data);
            WsClient2.processDataQueue();
            // console.log("onPackage3", data.data.length)
            break;
    }
};

module.exports = { WsClient2 };